package com.example.demo.websocket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collection;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author x c
 * @Email 378661553@qq.com
 * @Date Created in 2020/1/14 10:14
 */
@ServerEndpoint(value = "/websocket/{userId}", subprotocols = {}, configurator = WebSocketConfig.class)
public class WebSocketServer {

    private final static Logger log = LoggerFactory.getLogger(WebSocketServer.class);

    /**
     * 用于统计连接数
     */
    private final static AtomicInteger onlineCount = new AtomicInteger(0);

    /**
     * key:{@link WebSocketServer#userId }
     * value:对应的WebSocketServer对象
     */
    private final static ConcurrentHashMap<String, WebSocketServer> webSocketServerMap = new ConcurrentHashMap<>();

    /**
     * 当前连接的用户id
     */
    private String userId;

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 用户的个人配置信息
     */
    private EndpointConfig config;


    /**
     * 每一次进行 OnOpen 时都会创建一个新的 WebSocketServer 对象
     *
     * @param userId
     * @param session
     * @param config
     */
    @OnOpen
    public void onOpen(@PathParam("userId") String userId, Session session, EndpointConfig config) {
        this.userId = userId;
        this.session = session;
        this.config = config;
        ConcurrentHashMap<String, WebSocketServer> webSocketServerMap = WebSocketServer.webSocketServerMap;
        webSocketServerMap.remove(userId);
        webSocketServerMap.put(userId, this);
        int currentCount = onlineCount.incrementAndGet();
        log.info("用戶{}加入！当前在线人数为：{},当前对象:{}", userId, currentCount, this);
        sendAllMessage("新人加入。。");
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Throwable error) {
        error.printStackTrace();
        log.error("发生错误信息:userId={},error={}", userId, error);
    }


    @OnClose
    public void onClose() {
        webSocketServerMap.remove(userId, this);
        onlineCount.decrementAndGet();
    }


    /**
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message) {
        sendMessage(message);
    }

    private void sendAllMessage(String message) {
        String prefix = "开始发送集体通知信息";
        log.info("{}：{}", prefix, message);
        try {
            Collection<WebSocketServer> allWebSocketServer = WebSocketServer.webSocketServerMap.values();
            allWebSocketServer.forEach(wsServer -> {
                wsServer.sendMessage(message);
            });
            log.info("{}【成功】：{}", prefix, message);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("{}【失败】：{}", prefix, message);
        }
    }

    /**
     * 实现服务器主动推送
     */
    private void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("给客户端发送信息失败：userId={},message={},errorMsg={}", userId, message, e.getMessage());
        }
    }

}
